package cn.fanxin.service;

import cn.fanxin.enums.ConstantEnum;
import cn.fanxin.tools.*;
import cn.fanxin.utils.FileUtils;
import cn.fanxin.utils.ShellUtils;

import java.util.HashMap;
import java.util.Properties;

import static cn.fanxin.tools.CommonSql.*;

/**
 * @Author：china-fanxin
 * @Website: https://fan-xin.cn
 * @Date 2023/3/2 18:00
 * @Description:
 * 解析程序执行模式: mode参数介绍：
 * 1 ： 解析配置文件生成当前账期SQL查询语句 （MC加工当期值，以文件形式导入adb的中间表）
 * 2 ： 解析配置文件生成当前账期SQL查询语句（adb加工当期值，直接插入adb的中间表）
 * 3 ： 依赖指标中间表本身具备的当期值，生成带有衍生值的SQL查询语句（带有 INSERT INTO）
 * 4 ：
 * 5 ：
 * 6 : 生成MC上加工指标及衍生值的SQL，并将结果插入MC的结果表
 */
public class ParseModeService {

    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 解析配置文件生成当前账期SQL查询语句 （MC加工当期值，以文件形式导入adb的中间表）
     * @Date 2023/3/2 21:03
     * @Param: [acctDate, kpiConfMap, etlConfMap]
     * @Return: void
     */
    public static void parseIndicatorByMode1(String acctDate, HashMap<String,String> kpiConfMap, Properties confProp){
        HashMap<String, HashMap<Integer, String>> etlConfMap = CommonCheck.etlConfMap;
        StringBuilder executeSql = new StringBuilder();
        if (CommonCheck.isRelationMap){
            executeSql.append(genBaseMCSelectSQL(kpiConfMap,CommonCheck.dstColList))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(CommonCheck.dstColList)+"\n");
        }else {
            executeSql.append(genBaseMCSelectSQL(kpiConfMap,etlConfMap.get("srcColMap")))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(etlConfMap.get("srcColMap"))+"\n");
        }
        FileUtils.fileOutPut(ConstantEnum.EXECUTE_SQL_PATH.getValue(),executeSql.toString());
        System.out.printf("INFO:临时执行文件存放路径\n"+ConstantEnum.EXECUTE_SQL_PATH.getValue()+"\n");
        ShellUtils.callShellByExec("odps -M -f "+ConstantEnum.EXECUTE_SQL_PATH.getValue()+" | sed -e '/^$/d' -e s'/\"//'g  -e 's/\\\\N//g' >" + ConstantEnum.OUTPUT_FILE_PATH.getValue());
//        ShellUtils.callShellByExec(CommonShell.genRmTmpExecSQLFile());
        ShellUtils.callShellByExec(CommonShell.genAdbDeleteShell(acctDate,kpiConfMap.get("KPI_CODE"),kpiConfMap.get("DST_ENTITY_NAME"),confProp));
//        ShellUtils.callShellByExec(CommonShell.genRmTmpDelSQLFile());
        ShellUtils.callShellByExec(CommonShell.genAdbImportShell(kpiConfMap.get("DST_ENTITY_NAME")));
//        ShellUtils.callShellByExec(CommonShell.genRmTmpOutFile());
    }


    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 多维指标的加工结果会超出 1万行，odps的select语句最大返回行数为 1万，所以需要将多维结果加工到MC的表里然后再导出入库ADB
     * @Date 2023/3/8 9:52
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode1Multi(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        String dstTable = kpiConfMap.get("DST_ENTITY_NAME");
        HashMap<String, HashMap<Integer, String>> etlConfMap = CommonCheck.etlConfMap;
        StringBuilder executeSql = new StringBuilder();
        executeSql.append("INSERT OVERWRITE TABLE ").append(dstTable).append("_").append(acctDate).append("_").append(kpiConfMap.get("KPI_CODE")).append("_TEMP");
        //生成MC对应多维指标当前账期临时表建表语句的查询语句
        ShellUtils.callShellByExec(CommonShell.genAdbDdlSql(acctDate,dstTable,kpiConfMap.get("KPI_CODE")));
        //生成MC对应多维指标临时表的建表语句
        ShellUtils.callShellByExec(CommonShell.genAdbDdlShell());
        if (CommonCheck.isRelationMap){
            executeSql.append(genBaseMCSelectSQL(kpiConfMap,CommonCheck.dstColList))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(CommonCheck.dstColList)+"\n");
        }else {
            executeSql.append(genBaseMCSelectSQL(kpiConfMap,etlConfMap.get("srcColMap")))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(etlConfMap.get("srcColMap"))+"\n");
        }
        //执行建表语句
        ShellUtils.callShellByExec("odps -f "+ConstantEnum.DDL_SQL_PATH.getValue());
        FileUtils.fileOutPut(ConstantEnum.EXECUTE_SQL_PATH.getValue(),executeSql.toString());
        CommonTool.outputInfoTip("odps -f "+ConstantEnum.EXECUTE_SQL_PATH.getValue());
        ShellUtils.callShellByExec("odps -f "+ConstantEnum.EXECUTE_SQL_PATH.getValue());
        CommonTool.outputInfoTip("odps -e 'tunnel download " + dstTable+"_"+acctDate+"_"+kpiConfMap.get("KPI_CODE")+"_TEMP "+ ConstantEnum.OUTPUT_FILE_PATH.getValue() + "'");
        ShellUtils.callShellByExec("odps -e 'tunnel download " + dstTable+"_"+acctDate+"_"+kpiConfMap.get("KPI_CODE")+"_TEMP "+ ConstantEnum.OUTPUT_FILE_PATH.getValue() + "'");
        CommonTool.outputInfoTip("odps -e 'drop table " + dstTable+"_"+acctDate+"_"+kpiConfMap.get("KPI_CODE")+"_TEMP "+ "'");
        ShellUtils.callShellByExec("odps -e 'drop table " + dstTable+"_"+acctDate+"_"+kpiConfMap.get("KPI_CODE")+"_TEMP "+ "'");
        ShellUtils.callShellByExec(CommonShell.genAdbDeleteShell(acctDate,kpiConfMap.get("KPI_CODE"),dstTable,confProp));
        ShellUtils.callShellByExec(CommonShell.genAdbImportKShell(dstTable));
    }


    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 解析配置文件生成当前账期SQL查询语句（adb加工当期值，直接插入adb的中间表）
     * @Date 2023/3/10 10:42
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode2(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        HashMap<String, HashMap<Integer, String>> etlConfMap = CommonCheck.etlConfMap;
        StringBuilder executeSql = new StringBuilder();
        //生成删除中间表历史账期语句
        CommonSql.genDeleteMidExecuteSql(acctDate,kpiConfMap);
        //打印中间表加工语句
        CommonPrint.printBaseMidSqlStart();
        executeSql.append(CommonSql.genDefineInsertMidSQL(acctDate,kpiConfMap,etlConfMap.get("dstColMap")));
        if (CommonCheck.isRelationMap){
            executeSql.append(genAdbBaseSelectSQL(acctDate,kpiConfMap,CommonCheck.dstColList))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(CommonCheck.dstColList)+"\n;");
        }else {
            executeSql.append(genAdbBaseSelectSQL(acctDate,kpiConfMap,etlConfMap))
                    .append(genBaseWhereSql(acctDate,kpiConfMap))
                    .append(genGroupBySql(etlConfMap.get("srcColMap"))+"\n;");
        }
        System.out.println(executeSql.toString());
    }


    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 基于指标中间表的当期值，解析生成对应的Adb衍生值加工语句。
     * @Date 2023/3/3 16:14
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode3(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        String executeSql;
        String executeSumSql;
        //CommonSql.FORMULATION 列包含 大括号，则其为一个计算指标，否则为基础指标
        if (CommonFun.isJSCode(kpiConfMap)){
            HashMap<Integer, String> jsEtlConf = new HashMap<>();
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkJsAll(acctDate,kpiConfMap,confProp);
            //计算指标来源表和目标表必然一致，无需检测ETL配置，只需要读取目标表的元数据信息，获取字段即可
            if (!CommonCheck.isRelationMap){
                jsEtlConf = CommonFun.getJSEtlConf(confProp, kpiConfMap);
            }else {
                //前期接口设计问题，此处为了快速修复Bug，拼接了本来不必要的处理逻辑🤣
                for (int i = 0; i < CommonCheck.dstColList.size(); i++) {
                    jsEtlConf.put(i, CommonCheck.dstColList.get(i));
                }
            }
            //计算指标
            executeSql = CommonSql.genJSDefineExecuteSql(acctDate,kpiConfMap,jsEtlConf,confProp);
            System.out.println(executeSql);
        }else{
            //基础指标
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkBaseAll(acctDate,kpiConfMap,confProp);
            if("MSS".equals(kpiConfMap.get("COMP_KPI_CLASS"))){
                //如果是M域指标，则来源表具备了指标结果表所有字段内容，可以一一对应进行平抽
                executeSql = CommonSql.genBaseMapExecuteSql(acctDate,kpiConfMap,confProp);
                System.out.println(executeSql);
            }else{
                //生成基础指标可执行语句方法
                executeSql = CommonSql.genBaseMc2AdbDefineExecuteSql(acctDate, kpiConfMap,confProp);
                System.out.println(executeSql);
            }
            if ("1".equals(kpiConfMap.get("IS_AREA_SUM"))){
                //生成基础指标汇总值计算语句
                executeSumSql = CommonSumSql.genBaseSumExecuteSql(acctDate, kpiConfMap);
                System.out.println(executeSumSql);
            }
            //生成基础指标相关联的计算指标加工语句
            //CommonSql.genAboutJsSql(acctDate,kpiConfMap,confProp);
        }
        //输出BDI流程中想要获取的信息
        CommonPrint.printBdiInfo(kpiConfMap,CommonFun.getJsList(kpiConfMap,confProp));
    }

    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 生成adb的中间表加工语句，并基于中间表生成衍生值加工语句
     * @Date 2023/3/11 13:07
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode4(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        String executeSql;
        String executeSumSql;
        //CommonSql.FORMULATION 列包含 大括号，则其为一个计算指标，否则为基础指标
        if (CommonFun.isJSCode(kpiConfMap)){
            HashMap<Integer, String> jsEtlConf = new HashMap<>();
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkJsAll(acctDate,kpiConfMap,confProp);
            //计算指标来源表和目标表必然一致，无需检测ETL配置，只需要读取目标表的元数据信息，获取字段即可
            if (!CommonCheck.isRelationMap){
                jsEtlConf = CommonFun.getJSEtlConf(confProp, kpiConfMap);
            }else {
                //前期接口设计问题，此处为了快速修复Bug，拼接了本来不必要的处理逻辑🤣
                for (int i = 0; i < CommonCheck.dstColList.size(); i++) {
                    jsEtlConf.put(i, CommonCheck.dstColList.get(i));
                }
            }
            //生成计算指标当期值加工语句（加工到中间表）
            parseIndicatorByMode6(acctDate,kpiConfMap,confProp);
            //计算指标
            executeSql = CommonSql.genJSDefineExecuteSql(acctDate,kpiConfMap,jsEtlConf,confProp);
            System.out.println(executeSql);
        }else{
            //基础指标
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkBaseAll(acctDate,kpiConfMap,confProp);
            if("MSS".equals(kpiConfMap.get("COMP_KPI_CLASS"))){
                //如果是M域指标，则来源表具备了指标结果表所有字段内容，可以一一对应进行平抽
                executeSql = CommonSql.genBaseMapExecuteSql(acctDate,kpiConfMap,confProp);
                System.out.println(executeSql);
            }else{
                parseIndicatorByMode2(acctDate,kpiConfMap,confProp);
                //生成基础指标可执行语句方法
                executeSql = CommonSql.genBaseMc2AdbDefineExecuteSql(acctDate, kpiConfMap,confProp);
                System.out.println(executeSql);
            }
            //生成基础指标相关联的计算指标加工语句
            //CommonSql.genAboutJsSql(acctDate,kpiConfMap,confProp);
            if ("1".equals(kpiConfMap.get("IS_AREA_SUM"))){
                //生成基础指标汇总值计算语句
                executeSumSql = CommonSumSql.genBaseSumExecuteSql(acctDate, kpiConfMap);
                System.out.println(executeSumSql);
            }
        }
        //输出BDI流程中想要获取的信息
        CommonPrint.printBdiInfo(kpiConfMap,CommonFun.getJsList(kpiConfMap,confProp));
    }

    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 通过导数至ADB，完全依赖adb环境进行加工的初代加工逻辑，使用公共流程 [F_DP_PUB_INDEX_PROCESS_指标加工] 进行调度
     * @Date 2023/3/3 16:08
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode5(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        String executeSql;
        String executeSumSql;
        //CommonSql.FORMULATION 列包含 大括号，则其为一个计算指标，否则为基础指标
        if (CommonFun.isJSCode(kpiConfMap)){
            HashMap<Integer, String> jsEtlConf = new HashMap<>();
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkJsAll(acctDate,kpiConfMap,confProp);
            //计算指标来源表和目标表必然一致，无需检测ETL配置，只需要读取目标表的元数据信息，获取字段即可
            if (!CommonCheck.isRelationMap){
                jsEtlConf = CommonFun.getJSEtlConf(confProp, kpiConfMap);
            }else {
                //前期接口设计问题，此处为了快速修复Bug，拼接了本来不必要的处理逻辑🤣
                for (int i = 0; i < CommonCheck.dstColList.size(); i++) {
                    jsEtlConf.put(i, CommonCheck.dstColList.get(i));
                }
            }
            //计算指标
            executeSql = CommonSql.genJSDefineExecuteSql(acctDate,kpiConfMap,jsEtlConf,confProp);
            System.out.println(executeSql);
        }else{
            //基础指标
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkBaseAll(acctDate,kpiConfMap,confProp);
            if("MSS".equals(kpiConfMap.get("COMP_KPI_CLASS"))){
                //如果是M域指标，则来源表具备了指标结果表所有字段内容，可以一一对应进行平抽
                executeSql = CommonSql.genBaseMapExecuteSql(acctDate,kpiConfMap,confProp);
                System.out.println(executeSql);
            }else{
                //生成基础指标可执行语句方法
                executeSql = CommonSql.genBaseDefineExecuteSql(acctDate, kpiConfMap,confProp);
                System.out.println(executeSql);
            }
            if ("1".equals(kpiConfMap.get("IS_AREA_SUM"))){
                //生成基础指标汇总值计算语句
                executeSumSql = CommonSumSql.genBaseSumExecuteSql(acctDate, kpiConfMap);
                System.out.println(executeSumSql);
            }
            //生成基础指标相关联的计算指标加工语句
            //CommonSql.genAboutJsSql(acctDate,kpiConfMap,confProp);
        }
        //输出BDI流程中想要获取的信息
        CommonPrint.printBdiInfo(kpiConfMap,CommonFun.getJsList(kpiConfMap,confProp));
    }

    /**
     * @Author: china-fanxin
     * @Website: https://fan-xin.cn
     * @Description: 生成MC上加工指标及衍生值的SQL，并将结果插入MC的结果表
     * @Date 2023/4/1 20:21
     * @Param: [acctDate, kpiConfMap, confProp]
     * @Return: void
     */
    public static void parseIndicatorByMode6(String acctDate,HashMap<String,String> kpiConfMap,Properties confProp){
        String executeSql;
        String executeSumSql;
        //CommonSql.FORMULATION 列包含 大括号，则其为一个计算指标，否则为基础指标
        if (CommonFun.isJSCode(kpiConfMap)){
            HashMap<Integer, String> jsEtlConf = new HashMap<>();
            //初步检查配置信息和调度信息是否匹配
            CommonCheck.checkJsAll(acctDate,kpiConfMap,confProp);
            //计算指标来源表和目标表必然一致，无需检测ETL配置，只需要读取目标表的元数据信息，获取字段即可
            if (!CommonCheck.isRelationMap){
                jsEtlConf = CommonFun.getJSEtlConf(confProp, kpiConfMap);
            }else {
                //前期接口设计问题，此处为了快速修复Bug，拼接了本来不必要的处理逻辑🤣
                for (int i = 0; i < CommonCheck.dstColList.size(); i++) {
                    jsEtlConf.put(i, CommonCheck.dstColList.get(i));
                }
            }
            //计算指标
            executeSql = CommonSql.genMcJSDefineExecuteSql(acctDate,kpiConfMap,jsEtlConf,confProp);
            System.out.println(executeSql);
        }else{
            //基础指标
            if("MSS".equals(kpiConfMap.get("COMP_KPI_CLASS"))){
                //如果是M域指标，则来源表具备了指标结果表所有字段内容，可以一一对应进行平抽
                executeSql = CommonSql.genMcBaseMapExecuteSql(acctDate,kpiConfMap,confProp);
                System.out.println(executeSql);
            }else{
                //生成基础指标可执行语句方法
                executeSql = CommonSql.genBaseMCDefineExecuteSql(acctDate, kpiConfMap,confProp);
                System.out.println(executeSql);
            }
            if ("1".equals(kpiConfMap.get("IS_AREA_SUM"))){
                //生成基础指标汇总值计算语句
                executeSumSql = CommonSumSql.genMcBaseSumExecuteSql(acctDate, kpiConfMap);
                System.out.println(executeSumSql);
                executeSql = executeSql + executeSumSql;
            }
        }
        FileUtils.fileOutPut(ConstantEnum.EXECUTE_SQL_PATH.getValue(),executeSql.toString());
        CommonTool.outputInfoTip("临时执行文件存放路径\n"+ConstantEnum.EXECUTE_SQL_PATH.getValue()+"\n");
//        CommonTool.outputInfoTip("odps -f "+ConstantEnum.EXECUTE_SQL_PATH.getValue());
//        ShellUtils.callShellByExec("odps -f "+ConstantEnum.EXECUTE_SQL_PATH.getValue());
        //输出BDI流程中想要获取的信息
        CommonPrint.printBdiInfo(kpiConfMap,CommonFun.getJsList(kpiConfMap,confProp));
    }
}
